﻿#region Imports
using System;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Threading;
using System.Windows.Forms;
using System.Windows.Forms.DataVisualization.Charting;
using CommonUtilities.Enums;
using CommonUtilities.Extensions;
using PerformanceExpert.Models;
#endregion

namespace PerformanceExpert.Views
{
    public partial class frmPerformanceExpert : Form
    {
        #region Declarations
        int totalHits = 0;
        int procCount = 0;
        #endregion

        #region Properties
        public ObservableCollection<ProcessList> AllProcesses { get; set; }
        #endregion

        #region Constructors
        public frmPerformanceExpert()
        {
            InitializeComponent();

            cmbChartType.PopulateControlWithEnum<SeriesChartType>(SeriesChartType.Column);
            dgvProcess.GenerateDGVColumns<ProcessList>(false);
            cmbSort.PopulateSortableProperties<ProcessList>(dgvProcess);
            cmbSort.SelectedValue = "ProductName";

            tmrPerformance.Start();
        }
        #endregion

        #region Events
        private void frmPerformanceExpert_Load(object sender, EventArgs e)
        {
            btnRefresh_Click(sender, e);

            btnSortDirectioner.Enabled = true;
            //btnSortDirectioner.IsAscending = false;
        }

        private void btnRefresh_Click(object sender, EventArgs e)
        {
            btnRefresh.Enabled = true;
            AllProcesses = Process.GetProcesses()._Select(proc =>
                new ProcessList
                {
                    ProcessId = proc.Id,
                    ProductName = GetFileVersionInfo(proc, "ProductName"),
                    ProcessName = proc.ProcessName,
                    Responding = proc.Responding,
                    FileName = GetMainModule(proc, "FileName").RemoveText("\\??\\"),
                    ModuleName = GetMainModule(proc, "ModuleName"),
                    Comments = GetFileVersionInfo(proc, "Comments"),
                    CompanyName = GetFileVersionInfo(proc, "CompanyName"),
                    InternalName = GetFileVersionInfo(proc, "InternalName"),
                    Language = GetFileVersionInfo(proc, "Language"),
                    LegalCopyright = GetFileVersionInfo(proc, "LegalCopyright"),
                    OriginalFilename = GetFileVersionInfo(proc, "OriginalFilename"),
                    ProductVersion = GetFileVersionInfo(proc, "ProductVersion")
                }).ToObservableCollection();

            LoadData();
            btnRefresh.Enabled = false;
        }

        private void cmbSort_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (cmbSort.Enabled)
            {
                tltipPerfExpert.SetToolTip(cmbSort, cmbSort.Text);
                LoadData();
            }
            else
                tltipPerfExpert.Hide(this);
        }

        private void btnSortDirectioner_OnSortChanged(object sender, EventArgs e)
        {
            LoadData();
        }

        private void btnTerminate_Click(object sender, EventArgs e)
        {
            throw new NotImplementedException("YET TO BE IMPLEMENTED");
        }

        private void btnMonitor_Click(object sender, EventArgs e)
        {
            throw new NotImplementedException("YET TO BE IMPLEMENTED");
        }

        private void tmrPerformance_Tick(object sender, EventArgs e)
        {
            int cpuPercent = Convert.ToInt32(GetCPUCounter());
            if (cpuPercent >= 90)
            {
                totalHits += 1;
                if (totalHits == 60) MessageBox.Show("ALERT 90% usage for 1 minute");
                totalHits = 0;
            }
            else
            {
                totalHits = 0;
            }

            lblCPUPercntg.Text = cpuPercent + " % CPU";
            lblOverUsage.Text = totalHits + " seconds over 20% usage";
        }
        #endregion

        #region Methods
        private string GetFileVersionInfo(Process process, string propName)
        {
            try
            {
                ProcessModule processModule = process.MainModule;
                FileVersionInfo fileVersionInfo = processModule.FileVersionInfo;
                return (string)fileVersionInfo.GetType().GetProperty(propName).GetValue(fileVersionInfo, null);
            }
            catch (Exception)
            {
                return "N/A";
            }
        }

        private string GetMainModule(Process process, string propName)
        {
            try
            {
                ProcessModule processModule = process.MainModule;
                return (string)processModule.GetType().GetProperty(propName).GetValue(processModule, null);
            }
            catch (Exception)
            {
                return "N/A";
            }
        }

        private void LoadData()
        {
            procCount = (int)AllProcesses.GetCount();

            eSortDirection sortDirection = btnSortDirectioner.IsAscending ? eSortDirection.Ascending : eSortDirection.Descending;
            AllProcesses = AllProcesses.OrderByProperty(cmbSort.SelectedValue.Coalesce<string>("Sort"), sortDirection).ToObservableCollection();
            cmbProcess.DataSource = lstProcess.DataSource = dgvProcess.DataSource = AllProcesses;

            cmbProcess.DisplayMember = lstProcess.DisplayMember = "ProcessId";
            cmbProcess.ValueMember = lstProcess.ValueMember = "ProductName";
        }

        public object GetCPUCounter()
        {
            PerformanceCounter cpuCounter = new PerformanceCounter();
            cpuCounter.CategoryName = "Processor";
            cpuCounter.CounterName = "% Processor Time";
            cpuCounter.InstanceName = "_Total";

            PerformanceCounter ramCounter = new PerformanceCounter("Memory", "Available MBytes");
            float freeRAM = ramCounter.NextValue();
            lblFreeRAM.Text = "Free RAM : " + freeRAM + "MB";

            //PerformanceCounter total_cpu = new PerformanceCounter("Process", "% Processor Time", "_Total");
            //PerformanceCounter process_cpu = new PerformanceCounter("Process", "% Processor Time", appName);

            string title = "{0} :: Total {1} processes :: Free RAM {2} MB :: {3}";
            this.Text = title.FormatTextFromParams(Application.ProductName, procCount, freeRAM, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff"));

            // will always start at 0
            dynamic firstValue = cpuCounter.NextValue();
            Thread.Sleep(1000);

            // now matches task manager reading
            dynamic secondValue = cpuCounter.NextValue();

            return secondValue;
        }

        /*
        private static int GetProcessorIdleTime(string selectedServer)
        {
            try
            {
                var searcher =
                   ManagementObjectSearcher
                     (@"\\" + selectedServer + @"\root\CIMV2",
                      "SELECT * FROM Win32_PerfFormattedData_PerfOS_Processor WHERE Name=\"_Total\"");

                ManagementObjectCollection collection = searcher.Get();
                ManagementObject queryObj = collection.Cast<ManagementObject>().First();

                return Convert.ToInt32(queryObj["PercentIdleTime"]);
            }
            catch (ManagementException e)
            {
                MessageBox.Show("An error occurred while querying for WMI data: " + e.Message);
            }
            return -1;
        }
        */
        #endregion
    }
}



/*
Win32_Process class
 * http://msdn.microsoft.com/en-us/library/aa394372%28VS.85%29.aspx

How To  (Almost) Everything In WMI via C# Part 2  Processes - CodeProject
 * http://www.codeproject.com/Articles/18146/How-To-Almost-Everything-In-WMI-via-C-Part-2-Proce

 * http://stackoverflow.com/questions/1253154/get-current-cpu-ram-and-disk-drive-usage-in-c-sharp

ABCD
 * http://www
*/
